<template>
  <div class="good-div__base">
    <div class="good-div__content">
      <nav class="good-nav__category">
        <div
          class="category-div__nav"
          v-for="(good, index) in goodsData"
          :key="good.name + 'n'"
          :class="{ 'category-div--nav__selected': index === currNavIndex }"
          @click="handleClickNav(index)"
        >
          <div class="category-div__text">
            <icon-comp v-if="good.type > -1" :iconType="good.type"></icon-comp
            >{{ good.name }}
          </div>
        </div>
      </nav>
      <ul class="good-ul__detail" ref="scrollWrapper">
        <!-- 下面的div是子容器 -->
        <div @scroll="handleScrollBSThrottle">
          <li
            v-for="category in goodsData"
            :key="category.name + 'c'"
            class="detail-li__category"
          >
            <h2 class="category-h2__title">{{ category.name }}</h2>
            <ul class="category-ul__base">
              <li
                v-for="food in category.foods"
                :key="food.name + 'f'"
                class="category-li__food"
              >
                <div class="food-div__img" @click="showDetail(food)">
                  <img :src="food.icon" class="food-img__icon" />
                </div>
                <div class="food-div__content">
                  <h3 class="food-h3__name">{{ food.name }}</h3>
                  <p class="food-p__desc" v-if="food.description">
                    {{ food.description }}
                  </p>
                  <p class="food-p__info">
                    <span class="food-span__info"
                      >月售{{ food.sellCount }}份</span
                    >
                    <span class="food-span__info"
                      >好评率{{ food.rating }}%</span
                    >
                  </p>
                  <span class="food-span__price">￥{{ food.price }}</span>
                  <span class="food-span__preprice" v-if="food.oldPrice"
                    >￥{{ food.oldPrice }}</span
                  >
                  <good-button
                    class="food-comp__control"
                    :count="food.foodCount"
                    @addItem="handleButtonEvent(food, $event)"
                    @minusItem="handleButtonEvent(food, $event)"
                    >{{ food.foodCount }}</good-button
                  >
                </div>
              </li>
            </ul>
          </li>
        </div>
      </ul>
    </div>
    <transition name="fade">
      <good-detail
        v-if="isDetailCompShow"
        :foodInfo="detailCompProp"
        @good-detail-hide="isDetailCompShow = false"
        @add-food="detailAddFood"
      ></good-detail>
    </transition>
    <shop-cart
      :deliveryPrice="deliveryPriceRef"
      :basePrice="basePriceRef"
      :cartItemList="shopCartPropList"
      @shopcart-update="handleButtonEvent"
      @clear-proplist="clearPropList"
    ></shop-cart>
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import BetterScroll from "@better-scroll/core";
import {
  reactive,
  ref,
  nextTick,
  Ref,
  defineComponent,
} from "@vue/composition-api";
import { checkDOMElem, throttleByFrame } from "./../../common/util/tool";
import axiosGet from "./../../common/util/request";
import { FoodInfo, Cordinate2D } from "./../../common/globalType";
import { storageAction } from "./../../common/util/storage";
import IconComp from "./../icon-comp/icon-comp.vue";
import ShopCart from "./../good-shopcart/good-shopcart.vue";
import GoodButton from "../good-button/good-button.vue";
import GoodDetail from "../good-detail/good-detail.vue";

interface GoodData {
  name: string;
  type: number;
  foods: FoodInfo[];
}

interface RefLike<T = number> {
  value: T;
}

interface DeliveryData {
  deliveryPrice: number;
  minPrice: number;
}

interface ShortCartProp {
  name: string;
  price: number;
  foodCount: number;
}

let cumulativeHeight = 0; // 商品列表项累计高度
let bS: null | BetterScroll = null; // BetterScroll组件

// 设置foodCount属性
function setFoodCount<T extends Array<GoodData>>(goodsData: T) {
  goodsData.forEach((data) => {
    data.foods.forEach((food: ShortCartProp) => {
      Vue.set(food, "foodCount", 0);
    });
  });
}

// 更新propList函数
function updateCartPropList<T extends Array<ShortCartProp>>(
  count: number,
  food: ShortCartProp,
  propList: T
) {
  const foodIndex: number = propList.indexOf(food); // 找到食物索引
  // 如果count更新为0，直接移除当前项
  if (count === 0) {
    propList.splice(foodIndex, 1);
    // 如果count更新为1且当前propList中不存在该物品，直接添加propList
  } else if (count >= 1 && foodIndex === -1) {
    propList.push(food);
  }
}

export default defineComponent({
  // 组件注册
  components: {
    IconComp,
    ShopCart,
    GoodButton,
    GoodDetail,
  },
  // setup钩子
  setup() {
    const goodsData: GoodData[] = reactive([]); // 商品数据的响应式对象
    const scrollWrapper: Ref<HTMLElement | null> = ref(null); // 滚动包装元素的响应式引用
    const deliveryPriceRef: Ref<number> = ref(0); // 配送价格的响应式引用
    const basePriceRef: Ref<number> = ref(0); // 起送价格的响应式应用
    const goodListHeight: number[] = [0]; // 商品列表项高度列表
    const currNavIndex: Ref<number> = ref(0); // 导航栏当前索引
    const shopCartPropList: Ref<ShortCartProp[]> = ref([]); // 购物车props列表
    const isDetailCompShow: Ref<boolean> = ref(false); // 是否展示详情组件
    const detailCompProp: Ref<FoodInfo | object> = ref({}); // 传给展示详情组件的prop
    // 节流后的处理BS滚动监听函数
    const handleScrollBSThrottle = throttleByFrame((position: Cordinate2D) => {
      const yDis = -Math.floor(position.y);
      for (let i = 0; i < goodListHeight.length - 1; i++) {
        if (yDis >= goodListHeight[i] && yDis < goodListHeight[i + 1]) {
          currNavIndex.value = i;
          break; // 找到对应区间直接跳出循环
        } else {
          currNavIndex.value = goodListHeight.length - 1;
        }
      }
    });
    // 初始化betterScroll函数
    const initBetterScroll = function (...els: HTMLElement[]) {
      els.forEach((el) => {
        // 初始化betterScroll组件
        bS = new BetterScroll(el, {
          probeType: 3,
          click: true,
        });
        bS.on("scroll", handleScrollBSThrottle); // 绑定节流监听时间
      });
    };
    // 左侧导航栏点击跳转函数
    const clickToSpecHeight = function (index: number) {
      const yDis: number = goodListHeight[index];
      const timeLag = 500;
      if (bS === null) return; // 如果bS未初始化直接返回
      bS.off("scroll"); // 点击时移除所有滚动相关事件
      bS.scrollTo(0, -yDis, timeLag);
      // 点击后监听是否完成滚动事件
      bS.on("scrollEnd", () => {
        if (bS === null) return; // 如果bS未初始化直接返回
        bS.on("scroll", handleScrollBSThrottle); // 滚动完成需要重新绑定监听
        bS.off("scrollEnd"); // 清空监听事件节省性能
      });
    };
    // 处理左侧导航栏点击函数
    const handleClickNav = function (index: number) {
      currNavIndex.value = index;
      clickToSpecHeight(index);
    };
    // 处理按钮事件函数
    const handleButtonEvent = function (food: ShortCartProp, count: number) {
      food.foodCount = count; // 修改原有的计数变量
      updateCartPropList(count, food, shopCartPropList.value); // 判断是否需要更新propList
    };
    // 清空propList函数
    const clearPropList = function () {
      while (shopCartPropList.value.length > 0) {
        const currItem: ShortCartProp = shopCartPropList.value.pop()!;
        currItem.foodCount = 0;
      }
    };
    // 展示详情组件函数
    const showDetail = function (food: FoodInfo) {
      isDetailCompShow.value = true;
      detailCompProp.value = food;
    };
    // 详情组件食物加入购物车函数
    const detailAddFood = function (food: FoodInfo) {
      food.foodCount = 1; // 更新食物计数
      updateCartPropList(food.foodCount, food, shopCartPropList.value); // 更新proplist
    };
    // 监听仓库传来的数据
    storageAction("deliveryData", deliveryPriceRef, basePriceRef);
    // 远程请求商品数据
    axiosGet("/api/goods").then((res) => {
      // 将取到的结果push进响应式数据中
      res.data.forEach((r: GoodData) => {
        goodsData.push(r);
      });
      // 设置食物计数属性
      setFoodCount(goodsData);
      // 在下次回调更新后，初始化betterScroll
      nextTick(() => {
        // 如果已经拿到DOM元素。直接初始化
        const scrollWrapperElem: HTMLElement = scrollWrapper.value!;
        if (checkDOMElem(scrollWrapperElem)) {
          initBetterScroll(scrollWrapperElem);
          const goodDOMList = scrollWrapperElem.firstChild!.childNodes;
          goodDOMList.forEach((elem) => {
            if (checkDOMElem(elem)) {
              cumulativeHeight += elem.clientHeight;
              goodListHeight.push(cumulativeHeight);
            }
          });
        }
      });
    });
    return {
      goodsData,
      scrollWrapper,
      handleClickNav,
      currNavIndex,
      handleScrollBSThrottle,
      deliveryPriceRef,
      basePriceRef,
      handleButtonEvent,
      shopCartPropList,
      clearPropList,
      isDetailCompShow,
      showDetail,
      detailAddFood,
      detailCompProp,
    };
  },
});
</script>

<style lang="stylus" scoped>
@import '../../common/style/mixin.styl';

$up-height = 176px;// 上方区域的高度
$line-color = solid 1px rgba(7, 17, 27, 0.1);
$default-color = #f3f5f7;
$nav-fontsize = 12px;
$nav-color = rgb(240, 20, 20);
$side-color = #d9dde1;
$nav-lineheight = 14px;
$cat-height = 54px;
$gray-highcolor = #d9dde1;
$food-titleheight = 26px;
$food-titlecolor = rgb(7, 17, 27);
$food-infocolor = rgb(147, 153, 159);
$food-infosize = 10px;
$food-prizesize = 14px;
$food-currprizecolor = rgb(240, 20, 20);

.fade-enter, .fade-leave-to {
  opacity: 0;
}

.fade-enter-active, .fade-leave-active {
  transition: opacity 0.3s ease-out;
}

.good-div__base {
  height: calc(100vh - 176px);
  box-sizing: border-box;
  padding-bottom: 48px;
  position: relative;

  // 上边界线
  &::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 1px;
    background-color: rgba(7, 17, 27, 0.1);
    z-index: 2; // 盖在表单上面

    @media (-webkit-device-pixel-ratio: 2), (-webkit-max-device-pixel-ratio: 2), (-webkit-min-pixel-ratio: 2) {
      .good-div__base::before {
        transform: scaleY(50%);
      }
    }
  }

  .good-div__content {
    display: flex;
    height: 100%;

    .good-nav__category {
      height: 100%;
      width: 80px;
      flex-basis: 80px;
      overflow-x: hidden;
      background-color: $default-color;
      font-size: $nav-fontsize;
      text-align: center;
      flex-shrink: 0; // 重要，不要让它缩小

      &::-webkit-scrollbar {
        display: none;
      }
    }

    .good-ul__detail {
      flex-grow: 1;
      height: inherit; // 继承父元素的高度
      overflow: hidden; // 重要！为了配合betterScroll

      .detail-li__category {
        text-align: left;

        .category-h2__title {
          background-color: $default-color;
          padding-left: 14px;
          border-left: 3px solid $gray-highcolor;
          font-size: $nav-fontsize;
          height: $food-titleheight;
          line-height: 2;
          color: rgb(147, 153, 159);
        }
      }
    }
  }

  .category-div__nav {
    line-height: $nav-lineheight;
    padding: 0px 12px;
    box-sizing: border-box;
    height: $cat-height;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;

    &::after {
      content: '';
      position: absolute;
      top: 100%;
      width: 56px;
      height: 1px;
      background-color: rgba(7, 17, 27, 0.1);
    }

    // 最后一个没有横线
    &:last-child::after {
      display: none;
    }

    @media (-webkit-device-pixel-ratio: 2), (-webkit-max-device-pixel-ratio: 2), (-webkit-min-pixel-ratio: 2) {
      &::after {
        transform: scaleY(0.5);
      }
    }

    &.category-div--nav__selected {
      background-color: white;
      transition: 0.3s background-color linear;

      .category-div__text {
        font-weight: 700;
      }

      &::after {
        display: none;
      }
    }
  }

  .food-div__content {
    flex-grow: 1;

    .food-h3__name {
      font-size: $nav-lineheight;
      line-height: $nav-lineheight;
      color: $food-titlecolor;
      padding: 2px 0 8px 0;
    }

    .food-p__desc {
      font-size: 8px;
      color: rgb(147, 153, 159);
      padding-bottom: 8px;
      line-height: 14px;
    }

    .food-p__info {
      line-height: 1;
      font-size: $food-infosize;
      color: $food-infocolor;
      margin-bottom: 8px;

      .food-span__info {
        vertical-align: top;
        padding-right: 12px;
      }
    }

    .food-span__price {
      color: $food-currprizecolor;
      font-weight: 700;
      font-size: $food-prizesize;
    }

    .food-span__preprice {
      padding-left: 10px;
      color: $food-infocolor;
      text-decoration: line-through;
      font-size: $food-infosize;
    }
  }

  .category-ul__base {
    padding: 0 18px;

    .category-li__food {
      padding: 18px 0;
      display: flex;
      position: relative; // 方便购物车按钮定位
      border-1px(rgba(7, 17, 27, 0.1), 2, 0.5);

      // 食物的最后一栏没有横线
      &:last-child::after {
        display: none;
      }

      .food-div__img {
        width: 67px;
        flex-shrink: 0;

        .food-img__icon {
          width: 57px;
          height: 57px;
          // margin-right 10px;
        }
      }

      .food-comp__control {
        position: absolute; // 购物车按钮定位
        bottom: 15px;
        right: 0;
      }
    }
  }

  .good-div__cart {
    // height: 40px;
  }
}
</style>
